#!/usr/bin/python
# -*- coding:utf-8 -*-
'''
参考：
https://docs.python.org/2/library/ctypes.html
http://blog.sina.com.cn/s/blog_6982136301010rsj.html
'''

#0.   导入python库 和 C动态库
import ctypes  
#import libc
ll = ctypes.cdll.LoadLibrary 
lib = ll("./test.so")

#1.  测试python传递int *到c中，c中把值改后，传回python
#1.1 构造int *
val=ctypes.c_int(42)
p_val = ctypes.pointer(val)
#1.2 传输前，输出值和指针
print "***********in python1.0 ******"
print "***********in python**********"
print "before change val=",val
print "befor change p_val=",p_val
print "***********in python**********"
#1.3 调用C函数
lib.return_value.argtypes=[ctypes.c_void_p]
lib.return_value(p_val)
print "***********in python**********"
#1.4 代码改值后，输出值和指针
print "after change val=",val
print "after change p_val=",p_val
print "***********in python**********"
print "\n"

#2.  测试python传递char *到c中，c把值改后，传回
#2.1 构造char *
#py_c_str=ctypes.c_char_p()
#p_str = ctypes.pointer(py_c_str)
#2.2 构造数组
print "***********in python2.0 ******"
print "***********in python**********"
p_str =  ctypes.create_string_buffer( "this is python str", 32)
print "p_str:",p_str
py_str1="haha"
py_c_str1=ctypes.c_char_p(py_str1)
p_str1 = ctypes.pointer(py_c_str1)
#传输前的值，输出值和指针
print "before change p_str value",p_str.value,"repr:",repr(p_str.value)
print "***********in python**********"
#2.3 设置参数类型和返回值类型并调用
lib.return_str.argtypes=[ctypes.c_char_p,ctypes.c_int]
lib.return_str.restype = ctypes.c_char_p
py_str1 = lib.return_str(p_str, len(p_str))
#2.4 输出返回值
#print "after change py_str:",py_str
print "***********in python**********"
print ("get the c return py_str1:%r"%py_str1)
print "***********in python**********"
print "\n"


#3.  测试python与c通过参数和返回值传递结构体
#3.1 在python中定义c中的结构体,并在python中构造实例
class POINT(ctypes.Structure):
	_fields_ = [("x", ctypes.c_int),
				("y", ctypes.c_int)]
point = POINT(100,200)
point_return = POINT(100,200)
#3.2 在python中设置调用c的参数类型和返回值类型,并调用
print "***********in python3.0 ******"
lib.return_point.argtypes=[POINT,]
lib.return_point.restype =POINT
point_return = lib.return_point(point)
#3.3 在python中输出返回值
print "***********in python**********"
print ("in python:x=%d,y=%d"%(point_return.x,point_return.y))
print "***********in python**********"
print "\n"

#4.  测试python与c通过参数和返回值传递结构体指针
#4.1 用3.1中定义的结构体，并在python中实例化
p_point = 			ctypes.pointer(point)
#p_point_return = 	ctypes.POINTER(POINT)()
p_point.contents.x=200
p_point.contents.y=2000
print "***********in python4.0 ******"
#4.2 在python中设置调用c的参数类型和返回值类型,并调用
lib.return_point_p.argtypes = [ctypes.POINTER(POINT),]
lib.return_point_p.restype  = ctypes.POINTER(POINT)
p_point_return = lib.return_point_p(p_point)
#3.3 在python中输出返回值
#在python中的指针有个"contents"属性，是结构体的值！！
print "***********in python**********"
print ("in python:x=%r,y=%r"%(p_point_return.contents.x,p_point_return.contents.y))
print "***********in python**********"
print ""
